home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-07-08 | 42.8 KB | 1,387 lines |
- Function USCensus$ZColors, PopulationChanges, PopulationScale
- ;
- ; Given a population change, determine the color that should be
- ; used for that State.
- ;
- NPopulations = N_Elements(PopulationChanges)
- Colors = BytArr(3, NPopulations)
- Loss = Where(PopulationChanges lt PopulationScale.RangeMax[0], NLoss)
- If (NLoss gt 0) then Begin
- For J = 0, 2 Do Begin
- Colors[J, Loss] = PopulationScale.Colors[J, 0]
- EndFor
- EndIf
- For I = 1, N_elements(PopulationScale.RangeMax) - 1 Do Begin
- ThisColor = Where(PopulationChanges ge $
- PopulationScale.RangeMax[I - 1] and $
- PopulationChanges lt PopulationScale.RangeMax[I], NThisColor)
- If (NThisColor ne 0) then Begin
- For J = 0, 2 Do Begin
- Colors[J, ThisColor] = PopulationScale.Colors[J, I]
- EndFor
- EndIf
- EndFor
- BigGain = Where(PopulationChanges ge PopulationScale.RangeMax[ $
- N_elements(PopulationScale.RangeMax) - 1], NBigGain)
- If (NBigGain ne 0) then Begin
- For J = 0, 2 Do Begin
- Colors[J, BigGain] = PopulationScale.Colors[J, $
- N_elements(PopulationScale.RangeMax) - 1]
- EndFor
- EndIf
- Return, Colors
- End
-
-
- Pro USCensus$New_Coordinates, States, XSize, YSize
- ;
- ; Calculate State outlines and extruded skirts in normalized
- ; coordinates based on the current window size. This routine
- ; is called on initialization.
- ;
- ;
- ; Save the relevant system variables.
- ;
- PSave = !p
- XSave = !x
- YSave = !y
- ZSave = !z
- ;
- ; Set up mapping so we can perform coordinate transforms
- ; from lat/long to normal coordinates.
- ;
- Window, /Free, /Pixmap, XSize = XSize, YSize = YSize
- Map_Set, 30., -90., Limit = [10.,-68.5, 60.,-120.5], /Lambert
- WDelete, !d.window
- ;
- ; Loop over States, converting lat/lon coordinates to normal
- ; coordinates, and extruding the outline along the Z axis to
- ; build the "sides" of the States. The Z height is random
- ; in this example, though we do have population data in the
- ; State structure.
- ;
- NPopulation = N_elements(States[0].Population) - 1
- For I = 0L, N_elements(States) - 1 Do Begin
- NewOutline = (Convert_Coord(*States[I].pOutline, /Data, $
- /To_Normal))
- NSize = N_elements(NewOutline)/3
- States[I].ZValue = 1.
- If (Ptr_Valid(States[I].pNormalOutline)) then Begin
- *States[I].pNormalOutline = NewOutline[*, 0:NSize - 1]
- EndIf Else Begin
- States[I].pNormalOutline = $
- Ptr_New(NewOutline[*, 0:NSize - 1])
- EndElse
- ;
- ; Meshing needs to have the first and last outline elements the same
- ; otherwise the surface doesn't close.
- ;
- NewOutline2 = FltArr(3, NSize + 1)
- NewOutline2[*, 0:NSize - 1] = NewOutline
- NewOutline2[*, NSize] = NewOutline[*, 0]
- Mesh_Obj, 5, VertexList, PolygonList, NewOutline2, P1 = 1, $
- P2 = [0, 0, States[I].ZValue]
- If (Ptr_Valid(States[I].pPolygonList)) then Begin
- *States[I].pPolygonList = Temporary(PolygonList)
- EndIf Else Begin
- States[I].pPolygonList = Ptr_New(PolygonList, /No_Copy)
- EndElse
- If (Ptr_Valid(States[I].pVertexList)) then Begin
- *States[I].pVertexList = Temporary(VertexList)
- EndIf Else Begin
- States[I].pVertexList = Ptr_New(VertexList, /No_Copy)
- EndElse
- EndFor
- ;
- ; Restore plotting environment that changed with MAP_SET.
- ;
- !x = XSave
- !y = YSave
- !z = ZSave
- !p = PSave
- Return
- End
-
-
- Pro USCensus$Build_Backdrop, BackdropImage, BackdropObject
- ;
- ; This routine builds the "curtain" or backdrop
- ; in front of which the map data are rendered.
- ; There's no real magic here. I just played around
- ; with the values until I got the effect I wanted.
- ;
- ; Note that when texture mapping, IDL operates most
- ; efficiently on images that are a) square and b)
- ; dimensioned by powers of 2.
- ;
- ; ZZ defines the surface "height" of the backdrop.
- ; XX and YY are the coordinates of each of the
- ; ZZ values.
- ;
- ; Since the image is not a true child of the
- ; backdrop object (it's a property), we need
- ; to pass that back so we can destroy it later.
- ;
- ZZ = Findgen(256)^7/1.E15 + .01
- Z = FltArr(256, 256)
- For I = 0, 255 Do Begin
- Z[I, *] = ZZ
- EndFor
- XX = FltArr(256, 256)
- YY = XX
- ;
- ; Center the X and Y values
- ;
- X = Reverse(.25 - Findgen(256)/512)
- Y = Findgen(256)/128 - 1
- ;
- ; The Y values of the mapped image are
- ; the same across a row. The X values
- ; spread out toward the bottom of the
- ; backdrop so the image appears "splayed".
- ;
- For I = 0, 255 Do Begin
- YY[I, *] = Y/10.
- XX[*, I] = X * (1 + ((255 - I)/128.)^1.5)
- EndFor
- ;
- ; Create the image that will be mapped onto
- ; the coordinates defined above, It's simply
- ; an image of vertical stripes with some border
- ; pixels.
- ;
- Image = BytArr(3, 256, 256)
- Image[*,254:*, *] = 255
- Image[*, *, 254:*] = 255
- Image[*,0:3, *] = 255
- Image[*, *, 0:2] = 255
- ;
- ; Now we get obnoxiously partiotic and make
- ; the stripes red, white, and blue with some
- ; black left in for "shadows".
- ;
- K = -1
- For X = 30, 220, 10 Do Begin
- K = (K + 1) mod 3
- If (K eq 1) then Begin
- Image[*, X:X + 5, *] = 255
- EndIf Else Begin
- For I = 0, 2 Do Begin
- Image[I, X:X + 5, *] = 255 * (I eq K)
- EndFor
- EndElse
- EndFor
- ;
- ; The next trick we perform is to de-focus the
- ; image in steps so that pixels nearest the
- ; top that appear farthest away are also the most
- ; out-of-focus.
- ;
- For Y = (Size(Image))[2] - 31, 0, -32 Do Begin
- For I = 0, 2 Do Begin
- ;
- ; Smooth pixels from this row up. Rows at the
- ; top are smoothed more often than rows at the
- ; bottom.
- ;
- Layer = Smooth(Reform(Image[I, *, Y:*]), 3)
- Image[I, *, Y:*] = Layer
- EndFor
- EndFor
- ;
- ; Create the backdrop image. Don't forget it's TrueColor!
- ;
- BackdropImage = Obj_New('IDLgrImage', Image, Interleave = 0)
- ;
- ; Create the backdrop object using the image object as the
- ; texture object. Keep in mind that the texture mapped image
- ; colors are convolved with the COLOR property of the surface
- ; object.
- ;
- BackdropObject = Obj_New('IDLgrSurface', .2 - Z/100., XX, YY, $
- Shading = 1, Style = 2, Texture_Map = BackdropImage, $
- Color = [255, 255, 255], /Texture_Interp)
- End
-
-
- Pro USCensus$Build_Scale_Legend, PopulationScale, TimesFont, $
- ScaleModel
- ;
- ; This routine builds the legend for the display. Each key
- ; consists of a color block and a text label associated
- ; with each color. Colors in this example represent relative
- ; population change from one decade to the next.
- ;
- ScaleModel = Obj_New('IDLgrModel')
- NScaleColors = N_elements(PopulationScale.RangeMax) + 2
- ScaleColorModels = ObjArr(NScaleColors)
- ScaleColorImages = ObjArr(NScaleColors)
- ScaleColorLabels = ObjArr(NScaleColors)
- ColorBlock = BytArr(3, 30, 20)
- ;
- ; The color white is used when a State is "new"; no census
- ; was performed the previous decade.
- ;
- ScaleColorImages[0] = Obj_New('IDLgrImage', ColorBlock + 255, $
- Interleave = 0, Dimensions = [.1, .2])
- ScaleColorLabels[0] = Obj_New('IDLgrText', 'New State', /OnGlass, $
- Location = [.11, -0.06], Color = [255, 255, 255], $
- Font = TimesFont)
- ;
- ; Red indicates there was population loss compared with the
- ; previous decade.
- ;
- Red = ColorBlock
- Red[0, *, *] = 255
- ScaleColorImages[1] = Obj_New('IDLgrImage', Red, Interleave = 0, $
- Dimensions = [.1, .2])
- ScaleColorLabels[1] = Obj_New('IDLgrText', 'Pop. Loss', /OnGlass, $
- Location = [.11, -0.06], Color = [255, 255, 255], $
- Font = TimesFont)
- ;
- ; The remaining keys indicate population change between one
- ; percentage and the next.
- ;
- For I = 2, NScaleColors - 1 Do Begin
- ThisColor = ColorBlock
- For J = 0, 2 Do Begin
- ThisColor[J, *, *] = PopulationScale.Colors[J, I - 1]
- EndFor
- ScaleColorImages[I] = Obj_New('IDLgrImage', ThisColor, $
- Interleave = 0, Dimensions = [0.1, 0.2])
- ScaleColorLabels[I] = Obj_New('IDLgrText', '> ' + $
- StrTrim(Fix(100*(PopulationScale.RangeMax[I - 2] - $
- .99999)), 2) + '%', $
- Color = [255, 255, 255], Location = [0.11, -0.06], $
- /OnGlass, Font = TimesFont)
- EndFor
- ;
- ; Combine the color blocks and text into a models, then
- ; translate them so we end up in 2 rows, each with 5 entries.
- ;
- For I = 0, NScaleColors - 1 Do Begin
- ScaleColorModels[I] = Obj_New('IDLgrModel')
- ScaleColorModels[I]->Add, ScaleColorImages[I]
- ScaleColorModels[I]->Add, ScaleColorLabels[I]
- ScaleColorModels[I]->Translate, -.94 + .4*(I mod 5), $
- -.575*(Fix(I/5)), 0.
- EndFor
- ScaleLabel = Obj_New('IDLgrText', 'Relative Population Change', $
- Location = [-.98, .6], Font = TimesFont, /OnGlass, $
- Color = [255, 255, 255])
- ScaleModel->Add, ScaleLabel
- ScaleModel->Add, ScaleColorModels
- End
-
-
- Pro USCensus$Build_State_Objects, States, StateSurfaceModel, $
- StateObjects, StateSkirts, StateFaces, StateOutlines
- ;
- ; Create a tessellator object. Since the State outlines
- ; are not all convex, we need to tessellate them before
- ; turning them into polygon objects.
- ;
- Tessellator = Obj_New('IDLgrTessellator')
- ;
- ; Build each of the State objects. State objects consist
- ; of a) a contiguous outline of the State, b) a filled
- ; polygon which serves as the face, and c) an extruded
- ; surface which is the "skirt" of the State.
- ;
- NStates = N_elements(States)
- StateSurfaceModel = Obj_New('IDLgrModel')
- StateObjects = ObjArr(NStates)
- StateSkirts = ObjArr(NStates)
- StateFaces = ObjArr(NStates)
- StateOutlines = ObjArr(NStates)
- For I = 0, NStates - 1 Do Begin
- NewOutline = *States[I].pNormalOutline
- ;
- ; Make sure lakes are blue. And that no one lives permanently
- ; in them. Note to Canadians: boundaries are cosmetic only.
- ; Neither the United States of America nor Research Systems, Inc.
- ; make any formal claims to territories displayed in the map
- ; data that do not actually represent previously agreed upon
- ; legal boundaries claimed by either entity.
- ;
- NewOutline[2, *] = States[I].ZValue
- If (StrPos(States[I].State, 'LAKE') ne -1) then Begin
- Color = [0, 0, 255]
- EndIf Else Begin
- Color = [255, i*3, i*5]
- EndElse
- ;
- ; Create the State model object.
- ;
- StateObjects[I] = Obj_New('IDLgrModel')
- ;
- ; A black outline serves as the State border. We define
- ; this first in the model so it will overlay the polygon
- ; face defined later. (They lie in the same plane.)
- ;
- StateOutlines[I] = Obj_New('IDLgrPolyline', NewOutline, $
- Color=[0, 0, 0], Thick = 1.2, Shading = 0)
- StateObjects[I]->Add, StateOutlines[I]
- ;
- ; Create the skirt for the State. Note that we specify
- ; backface culling. Since we won't be looking at the
- ; "inside" or back of the scene, we can speed rendering
- ; by telling IDL to reject back faces.
- ;
- StateSkirts[I] = Obj_New('IDLgrPolygon',*States[I].pVertexList, $
- Polygon = *States[I].pPolygonList, Color = Color, $
- Shading = 1, Reject = 1)
- StateObjects[I]->Add, StateSkirts[I]
- ;
- ; Create the top face of the State. We don't define
- ; the polygon outlines until a little later after
- ; we tessellate the polygon.
- ;
- StateFaces[I] = Obj_New('IDLgrPolygon', $
- Color = Color, Shading = 0, Reject = 1)
- StateObjects[I]->Add, StateFaces[I]
- ;
- ; Set the UValue of the State object to the State's name.
- ;
- StateObjects[I]->SetProperty, UValue = States[I].State
- ;
- ; The following tessellation code compensates for the "concave
- ; polygon problem". Tessellate the outline.
- ;
- Tessellator->AddPolygon, NewOutline*500.
- ;
- ; Precalculate the normals; all the faces point straight up.
- ;
- If (Tessellator->Tessellate(Vertices, Polygons)) then Begin
- ;
- ; Define the State face outline from the tesselation results.
- ; We precalculate the normals since we know the faces are all
- ; perpendicular to the +Z axis. This saves some calculation
- ; time for IDL.
- ;
- Normals = Vertices
- Normals[0:1, *] = 0.
- Normals[2, *] = 1.
- StateFaces[I]->SetProperty, Data = Vertices/500., $
- Polygons = Polygons, Normals = Normals
- EndIf
- ;
- ; Translate Alaska and Hawaii so they lie closer to the
- ; continental USA.
- ;
- If (States[I].State eq 'ALASKA') then Begin
- StateObjects[I]->Translate, 0., -.15, 0.
- StateObjects[I]->Translate, -.05, 0., 0.
- EndIf
- If (States[I].State eq 'HAWAII') then Begin
- StateObjects[I]->Translate, .125, 0., 0.
- StateObjects[I]->Translate, 0., -.05, 0.
- EndIf
- ;
- ; Add the State to the model. Also reset the
- ; tessellator so we're only working on one polygon
- ; at a time.
- ;
- StateSurfaceModel->Add, StateObjects[I]
- Tessellator->Reset
- EndFor
- ;
- ; We don't need the tessellator anymore.
- ;
- Obj_Destroy, Tessellator
- End
-
-
- Pro USCensus$Display_Census_Year, AppState
- ;
- ; Translate the surface back to the XY plane so we can
- ; rotate it about the Y axis.
- ;
- AppState.StateSurfaceModel->Translate, 0., 0., -.5
- ;
- ; Rotate the plane about Y back to 0 degrees, then rotate
- ; it the specified number of degrees relative to 0.
- ;
- AppState.StateSurfaceModel->GetProperty, Transform = Transform
- ThetaY = ATan(Transform[2, 0], Transform[0, 0])/!dtor
- AppState.StateSurfaceModel->Rotate, [0., 1., 0.], -ThetaY
- AppState.StateSurfaceModel->Rotate, [0., 1., 0.], AppState.ThetaY
- ;
- ; Translate the surface back toward the viewer along Z.
- ;
- AppState.StateSurfaceModel->Translate, 0., 0., .5
- ZeroPops = Where(AppState.States.Population[ $
- AppState.CurrentYearIndex] eq 0, NZeroPops)
- OkayPops = Where(AppState.States.Population[ $
- AppState.CurrentYearIndex] ne 0, NOKayPops)
- ;
- ; For States that had no census taken for a given decade,
- ; we just draw dark gray boxes at Z = very nearly zero.
- ; Lakes are always blue.
- ;
- For I = 0, NZeroPops - 1 Do Begin
- If (StrPos(AppState.States[ZeroPops[I]].State, 'LAKE') $
- eq -1) then Begin
- AppState.StateFaces[ZeroPops[I]]->SetProperty, $
- Color = [20, 20, 20]
- EndIf
- If (AppState.PreviousScales[ZeroPops[I]] ne 1.e-4) then Begin
- AppState.PreviousScales[ZeroPops[I]] = 1.e-4
- AppState.StateObjects[ZeroPops[I]]->Scale, 1., 1., 1.e-4
- EndIf
- EndFor
- ;
- ; Determine the color to draw the State based on the population
- ; change from the previous decade.
- ;
- If (AppState.CurrentYearIndex lt $
- N_elements(AppState.States[0].Population) - 1) then Begin
- Colors = USCensus$ZColors(AppState.States.Population[ $
- AppState.CurrentYearIndex]/ $
- Float(AppState.States.Population[ $
- AppState.CurrentYearIndex + 1]), $
- AppState.PopulationScale)
- EndIf
- ;
- ; Label the census year.
- ;
- AppState.TextObject->SetProperty, String = $
- StrTrim(1980 - (AppState.CurrentYearIndex - 1)*10, 2)
- ;
- ; Loop over the States for which there are valid (non-zero) census
- ; data for this decade.
- ;
- For I = 0, NOkayPops - 1 Do Begin
- ThisState = OkayPops[I]
- ;
- ; Set the Z scale of the object so that the previous decade = 1 at
- ; the current height. This allows us to calculate a relative scale
- ; based on the population change.
- ;
- AppState.StateObjects[ThisState]->GetProperty, $
- Transform = Transform
- AppState.StateObjects[ThisState]->Scale, 1., 1., $
- 1./Transform[2, 2]
- ;
- ; Scale the height of the State relative to the maximum population.
- ;
- ZScale = AppState.States[ThisState].Population[ $
- AppState.CurrentYearIndex]/ $
- AppState.MaxZValue
- AppState.StateObjects[ThisState]->Scale, 1., 1., ZScale
- ;
- ; Determine the color to make the State, based on relative population
- ; change from the previous decade.
- ;
- If (StrPos(AppState.States[ThisState].State, 'LAKE') eq -1) $
- then Begin
- If (AppState.CurrentYearIndex eq $
- N_elements(AppState.States[0].Population) - 1) then Begin
- ;
- ; If we're in the first year of the census, make the States white.
- ;
- Color = [255, 255, 255]
- EndIf Else Begin
- If (AppState.States[ThisState].Population[ $
- AppState.CurrentYearIndex + 1] eq 0) then Begin
- ;
- ; If the State did not have a census performed in the previous decade,
- ; color the State white.
- ;
- Color = [255, 255, 255]
- EndIf Else Begin
- ;
- ; We had census data from the previous decade, so color the State
- ; appropriately.
- ;
- Color = Reform(Colors[*, ThisState])
- EndElse
- EndElse
- AppState.StateSkirts[ThisState]->SetProperty, Color = Color
- AppState.StateFaces[ThisState]->SetProperty, Color = Color
- EndIf
- ;
- ; If we're on a fast machine, we might want to animate the States
- ; individually growing.
- ;
- If (AppState.AnimateStates) then Begin
- Dummy = Check_Math()
- AppState.WindowObject->Draw, AppState.ViewObjects[0], $
- Draw_Instance = AppState.Backdrop
- EndIf
- AppState.PreviousScales[OkayPops[I]] = ZScale
-
- EndFor
- ;
- ; If we're not instancing the data, then just draw the view.
- ;
- Dummy = Check_Math()
- If (AppState.AnimateStates eq 0) then Begin
- AppState.WindowObject->Draw, AppState.ViewObjects[0], $
- Draw_Instance = AppState.Backdrop
- EndIf
- ;
- ; Clean up any divide by zero, messages that may have
- ; accumulated.
- ;
- Dummy = Check_Math()
- End
-
-
- ;Pro USCensus$Animate_Census, AppState
- ;
- ; Loop over the census years.
- ;
- ;For J = N_elements(AppState.States[0].Population) - 1, 0, -1 $
- ; Do Begin
- ;
- ; We rotate the plane on which the States sit at each decade
- ; to enhance the relief in the early years of the census and
- ; to focus primarily on the east coast.
- ;
- ; AppState.ThetaY = -(J + 4) * 1.25
- ; AppState.CurrentYearIndex = J
- ; Widget_Control, AppState.ThetaYSlider, $
- ; Set_Value = AppState.ThetaY
- ; USCensus$Display_Census_Year, AppState
- ;EndFor
- ;End
-
-
- Pro USCensus$Cleanup, AppState, TLB
- ;
- ; Handle the widget destruction through a File/Exit or
- ; system menu close.
- ;
- Widget_Control, TLB, Get_UValue = AppState
- Obj_Destroy, AppState.ViewObjects[0]
- Obj_Destroy, AppState.ViewObjects[1]
- Obj_Destroy, AppState.BackdropImage
- Obj_Destroy, AppState.WindowObject
- Obj_Destroy, AppState.Fonts[0]
- Obj_Destroy, AppState.Fonts[1]
- Widget_Control, TLB, /Destroy
- ;
- ; Free the pointers. Save the whales.
- ;
- Ptr_Free, AppState.States.pOutline
- Ptr_Free, AppState.States.pNormalOutline
- Ptr_Free, AppState.States.pHighResOutline
- Ptr_Free, AppState.States.pLowIndices
- Ptr_Free, AppState.States.pPolygonList
- Ptr_Free, AppState.States.pVertexList
- End
-
-
- Pro D_USCensus_Event, Event
- ;
- ; This routine is the main event handler for the widget.
- ;
- Widget_Control, /Hourglass
- If (Tag_Names(Event, /Structure_Name) eq 'WIDGET_KILL_REQUEST') $
- then Begin
- USCensus$Cleanup, AppState, Event.Top
- !except = AppState.ExceptSave
- Return
- EndIf
- If (Tag_Names(Event, /Structure_Name) eq 'WIDGET_BASE') then Begin
- ;
- ; Handle resize events on the top level base.
- ;
- Widget_Control, /Hourglass
- Widget_Control, Event.Top, Get_UValue = AppState
- ;
- ; Size the draw windows appropriately, given the new dimensions
- ; of the base.
- ;
- ScaleGeom = Widget_Info(AppState.wScale, /Geometry)
- ButtonBaseGeom = Widget_Info(AppState.wControls, /Geometry)
- Widget_Control, AppState.wDraw, XSize = Event.X - $
- ButtonBaseGeom.XSize, $
- YSize = Event.Y - ScaleGeom.YSize
- Widget_Control, AppState.wScale, XSize = Event.X - $
- ButtonBaseGeom.XSize
- Widget_Control, Event.ID, XSize = Event.X, YSize = Event.Y
- ;
- ; Resize the backdrop, if it's there, and create the
- ; new instance.
- ;
- If (AppState.Backdrop) then Begin
- AppState.ViewObjects[0]->SetProperty, Transparent = 0
- AppState.StateSurfaceModel->SetProperty, Hide = 1
- AppState.TextObject->SetProperty, Hide = 1
- AppState.BackdropModel->SetProperty, Hide = 0
- AppState.WindowObject->Draw, AppState.ViewObjects[0], $
- /Create_Instance
- AppState.StateSurfaceModel->SetProperty, Hide = 0
- AppState.TextObject->SetProperty, Hide = 0
- AppState.BackdropModel->SetProperty, Hide = 1
- AppState.ViewObjects[0]->SetProperty, Transparent = 1
- EndIf
- ;
- ; Draw the view.
- ;
- AppState.WindowObject->Draw, AppState.ViewObjects[0], $
- Draw_Instance = AppState.Backdrop
- AppState.ScaleObject->Draw, AppState.ViewObjects[1]
- Widget_Control, Event.Top, /Clear_Events
- Return
- EndIf
- Widget_Control, Event.Top, Get_UValue = AppState
- Widget_Control, Event.ID, Get_UValue = UValue
- Case UValue of
- 'Quit' : Begin
- USCensus$Cleanup, AppState, Event.Top
- Return
- End
- 'Draw' : Begin
- ;
- ; Left mouse button press events cause the selected
- ; State's name to be displayed by the text object.
- ;
- Case Event.Type of
- 0 : Begin
- If (Event.Press eq 1) then Begin
- Widget_Control, /Hourglass
- Picked = AppState.WindowObject->Select( $
- AppState.ViewObjects[0], [Event.X, Event.Y])
- If (N_elements(Picked) ne 0) then Begin
- If (Obj_Valid(Picked[0])) then Begin
- If (Obj_IsA(Picked[0], 'idlgrmodel')) $
- then Begin
- Picked[0]->IDLGrModel::GetProperty, $
- Parent = ParentObject
- EndIf Else Begin
- Picked[0]->GetProperty, Parent = $
- ParentObject
- EndElse
- ParentObject->GetProperty, UValue = StateName
- ;
- ; If the object is a State, put the State's name "on the glass".
- ; Redrawing the entire scene shouldn't be necessary but I don't
- ; know the technique for just getting the text object to change.
- ;
- If (N_elements(StateName) ne 0) then Begin
- StateName = StateName[0]
- USState = Where(AppState.States.State $
- eq StateName, NState)
- If (NState ne 0) then Begin
- AppState.TextObject->SetProperty, $
- String = $
- AppState.States[USState[0]].State
- ; AppState.ViewObjects[1]->SetProperty, Hide = 1
- ; AppState.WindowObject->Draw, AppState.ViewObjects[0], /Draw_Instance
- ; AppState.ViewObjects[1]->SetProperty, Hide = 0
- Dummy = Check_Math()
- AppState.WindowObject->Draw, $
- AppState.ViewObjects[0]
- EndIf
- EndIf
- EndIf
- EndIf
- EndIf
- End
- 4 : Begin
- ;
- ; We got an EXPOSE event on one of the draw windows.
- ;
- AppState.ScaleObject->Draw, AppState.ViewObjects[1]
- AppState.WindowObject->Draw, AppState.ViewObjects[0]
- Widget_Control, Widget_Info(Event.ID, /Parent), /Clear_Events
- End
- Else:
- EndCase
- End
- 'CancelAnimation' : Begin
- Widget_Control, AppState.AnimateButton, Set_Value = 'Animate Census', $
- Set_UValue = 'Animate'
- Widget_Control, Event.Top, /Clear_Events
- End
- 'DoingAnimation' : Begin
- ;
- ; This event is thrown from the controls base. We use a timer event off
- ; this base to indicate "frame advance" in the animation.
- ;
- If (AppState.CurrentYearIndex ne 0) then Begin
- ;
- ; Decrement the year counter (move forward in time), move the slider
- ; rotation angle widget, and display the data.
- ;
- AppState.CurrentYearIndex = AppState.CurrentYearIndex - 1
- AppState.ThetaY = -(AppState.CurrentYearIndex + 4) * 1.25
- Widget_Control, AppState.ThetaYSlider, $
- Set_Value = AppState.ThetaY
- USCensus$Display_Census_Year, AppState
- ;
- ; Throw a timer event from the controls base. This will put us right
- ; back here into this case switch.
- ;
- Widget_Control, AppState.wControls, Timer = .001
- EndIf Else Begin
- ;
- ; We've reached the end of the animation, 1990. Reset the "Animate Census"
- ; button back to its original state, and clear the events.
- ;
- Widget_Control, AppState.AnimateButton, Set_Value = 'Animate Census', $
- Set_UValue = 'Animate'
- Widget_Control, Event.Top, /Clear_Events
- EndElse
- End
- 'Animate' : Begin
- ;
- ; Modify the "Animate Census" Button so it will now throw "CancelAnimation"
- ; events.
- ;
- AppState.StateSurfaceModel->SetProperty, $
- Transform = AppState.InitialTransform
- Widget_Control, AppState.AnimateButton, $
- Set_Value = 'Cancel Animation', $
- Set_UValue = 'CancelAnimation'
- ;
- ; Set the year index to point to 1790.
- ;
- AppState.CurrentYearIndex = N_elements(AppState.States[0].Population); - 1
- ;
- ; Toss a timer event from the controls base. Events from the controls
- ; base are interpreted as being "animation frame advance" events.
- ;
- Widget_Control, AppState.wControls, Timer = .001
- End
- 'Legend' : Begin
- AppState.ScaleObject->Draw, AppState.ViewObjects[1]
- AppState.WindowObject->Draw, AppState.ViewObjects[0]
- End
- 'CensusYear' : Begin
- AppState.CurrentYearIndex = $
- N_elements(AppState.States[0].Population) - Event.Value
- USCensus$Display_Census_Year, AppState
- Widget_Control, Event.ID, /Clear_Events
- End
- 'YRotation' : Begin
- AppState.ThetaY = Event.Value
- ;
- ; If individual state animation was in effect, turn it
- ; off for the rotation since it serves a purpose only
- ; in year changes.
- ;
- AnimateStates = AppState.AnimateStates
- AppState.AnimateStates = 0
- USCensus$Display_Census_Year, AppState
- AppState.AnimateStates = AnimateStates
- Widget_Control, Event.ID, /Clear_Events
- End
- 'HelpCensusData' : Begin
- If (not XRegistered('About Census Data')) then Begin
- TextTLB = Widget_Base(Group_Leader = Event.Top, /Column)
- Widget_Control, TextTLB, TLB_Set_Title = $
- 'About the Census Data'
- T = Widget_Text(TextTLB, XSize = 60, YSize = 15, $
- Value = AppState.DataText, /Scroll)
- OkayButton = Widget_Button(TextTLB, Value = 'OK', $
- UValue = 'KillAboutCensus')
- Widget_Control, TextTLB, /Realize
- XManager, 'About Census Data', TextTLB, Event_Handler = $
- 'D_USCensus_Event'
- EndIf
- End
- 'HelpCensusDemo' : Begin
- If (not XRegistered('About Census Demo')) then Begin
- TextTLB = Widget_Base(Group_Leader = Event.Top, /Column)
- Widget_Control, TextTLB, TLB_Set_Title = $
- 'About the Census Demo'
- T = Widget_Text(TextTLB, XSize = 60, YSize = 15, $
- Value = AppState.DemoText, /Scroll)
- OkayButton = Widget_Button(TextTLB, Value = 'OK', $
- UValue = 'KillAboutCensus')
- Widget_Control, TextTLB, /Realize
- XManager, 'About Census Demo', TextTLB, Event_Handler = $
- 'D_USCensus_Event'
- EndIf
- End
- 'KillAboutCensus' : Begin
- Widget_Control, Event.Top, /Destroy
- Return
- End
- Else :
- EndCase
- Widget_Control, Event.Top, Set_UValue = AppState
- End
-
- ;-----------------------------------------------------------------
- ;
- ; PURPOSE : cleanup procedure. restore colortable.
- ;
- pro USCensus_Cleanup, wTopBase
-
- WIDGET_CONTROL, wTopBase, GET_UVALUE=sState, /NO_COPY
-
- ; Restore the color table.
- ;
- TVLCT, sState.colorTable
-
- if widget_info(sState.groupBase, /valid) then $
- widget_control, sState.groupBase, /map
-
- end ; of USCensus_Cleanup
-
-
- Pro D_Uscensus, XSize = XSize, YSize = YSize, Axes = Axes, $
- Animate_States = Animate_States, Backdrop = Backdrop, $
- New_England = New_England, Depth = Depth, $
- Group_Leader = Group_Leader, AppTLB = AppTLB
- ;+
- ; FILE:
- ; D_Uscensus.pro
- ;
- ; CALLING SEQUENCE: D_Uscensus [, GROUP_LEADER = GROUP_LEADER $]
- ; [, XSIZE = XSIZE $]
- ; [, YSIZE = YSIZE $]
- ; [, /AXES $]
- ; [, /ANIMATE_STATES $]
- ; [, /NEW_ENGLAND $]
- ; [, /BACKDROP $]
- ; [, /DEPTH]
- ;
- ; PURPOSE:
- ; This application also illustrates handling draw widget base
- ; resizing and exposure events in the context of Object
- ; Graphics, pointer and object heap variable management and
- ; cleanup, and, when /BACKDROP is enabled, instancing of IDLgrView
- ; objects and image texture mapping to an IDLgrSurface object.
- ;
- ; The RGB Object Graphics color model is used exclusively in this
- ; demo; None of the code uses Color Index (CI) model.
- ;
- ; The procedure was authored by the Professional Services Group
- ; of Research Systems. For those desiring a larger
- ; implementation, we can be contacted (psg@rsinc.com) for
- ; consulting and custom coding.
- ;
- ; KEYWORD PARAMETERS:
- ; GROUP_LEADER can be set to the ID of a parent widget when
- ; this routine is called as a compound widget.
- ;
- ; APPTLB returns the application top level base, mainly for
- ; use in the IDL Demo (i.e., don't worry about this if you
- ; aren't RSI.)
- ;
- ; XSIZE, YSIZE can be used to define the size of the main
- ; draw window. By default, the values are 467 and 376 pixels,
- ; respectively.
- ;
- ; /AXES specifies that lines showing the X, Y, and Z
- ; axes should be rendered. By default these are not shown.
- ;
- ; /ANIMATE_STATES when set allows States to be individually
- ; rendered when a new year of data is displayed. By default
- ; all States are scaled before the view is rendered. This
- ; option is recommended only on machines with good rendering
- ; speed, such as a Pentium Pro 200 or Sun Ultra.
- ;
- ; /BACKDROP when set causes a backdrop image to be drawn behind
- ; the USA map. It's a good example of view object instancing.
- ; This is recommended only for machines with TrueColor displays
- ; and good rendering speed. By default, the backdrop image is
- ; not displayed.
- ;
- ; /DEPTH turns on depth cueing in the view. By default, depth
- ; cueing is not performed.
- ;
- ; RETURN VALUE:
- ; MAJOR TOPICS: Visualization, Analysis, Demo, Language
- ;
- ; CATEGORY:
- ; IDL 5.0
- ;
- ; INTERNAL FUNCTIONS and PROCEDURES:
- ; fun USCensus$ZCOLORS - Determine color to shade State
- ; objects based on population
- ; gain or loss.
- ; pro USCensus$NEW_COORDINATES
- ; - Turn latitutde/longitudes for
- ; State outlines into device
- ; coordinates, and build the
- ; "skirts".
- ; pro USCensus$BUILD_BACKDROP
- ; - Build the backdrop "drapery"
- ; objects
- ; pro USCensus$BUILD_SCALE_LEGEND
- ; - Build the legend for the display
- ; pro USCensus$BUILD_STATE_OBJECTS
- ; - Build the individual State
- ; objects
- ; pro USCensus$DISPLAY_CENSUS_YEAR
- ; - Draw the scene for the currently
- ; selected year
- ; pro USCensus$ANIMATE_CENSUS
- ; - Animate the census data from 1790
- ; to 1990
- ; pro USCensus$CLEANUP - Clean up objects and heap
- ; variables when the application
- ; is completed.
- ; pro USCensus_EVENT - The main event handler
- ;
- ; EXTERNAL FUNCTIONS, PROCEDURES, and FILES:
- ; states.sav - IDL SAVE file containing State
- ; outlines and Census data.
- ;
- ; REFERENCE: IDL Reference Guide, IDL User's Guide
- ;
- ; NAMED STRUCTURES:
- ; none.
- ;
- ; COMMON BLOCKS:
- ; none.
- ;
- ; SYSTEM VARIABLES:
- ; none.
- ;
- ; MODIFICATION HISTORY:
- ; 3/97, JLP - Completed version for IDL 5.0.
- ; 4/11/97, JLP - Restricted rotation angle selection
- ; Added ability to stop animation
- ; Modified viewport size
- ; Added check_math() traps for text objects
- ;-
- ;--------------------------------------------------------------------
- If (XRegistered('D_Uscensus', /NoShow)) then Begin
- v = Dialog_Message('An instance of D_Uscensus is already running.')
- Return
- EndIf
- If (N_elements(Group_Leader) ne 0) then Begin
- If (N_elements(Group_Leader) eq 1) then Begin
- OkayGL = Widget_Info(Group_Leader, /Valid_ID)
- EndIf Else Begin
- OkayGL = 0
- EndElse
- If (not OkayGL) then Begin
- v = Dialog_Message('The GROUP_LEADER parameter is invalid.')
- Return
- EndIf
- groupBase = Group_Leader
- EndIf else groupBase = 0L
-
- ngroup = N_elements(Group_Leader)
-
- ; ; Create the starting up message.
- ; ;
- ; if (ngroup EQ 0) then begin
- ; drawbase = startmes()
- ; endif else begin
- ; drawbase = startmes(GROUP=group)
- ; endelse
-
- ; Get the current color vectors to restore
- ; when this application is exited.
- ;
- TVLCT, savedR, savedG, savedB, /GET
-
- ; Build color table from color vectors
- ;
- colorTable = [[savedR],[savedG],[savedB]]
-
- ; Get the tips.
- ;
- ; sText = getTips('uscensus.tip')
- sText = getTips(filepath('uscensus.tip', $
- SUBDIR=['examples','demo', 'demotext']) )
-
-
- ;
- ; On slow platforms, we only use New England.
- ;
- NewEnglandStates = ['MAINE', 'NEW HAMPSHIRE', 'VERMONT', $
- 'MASSACHUSETTS', 'CONNECTICUT', 'RHODE ISLAND']
- NewEngland = Keyword_Set(New_England)
- If (Keyword_Set(Depth)) then Begin
- Depth_Cue = [-1.5, 1.]
- EndIf Else Begin
- Depth_Cue = [0., 0.]
- EndElse
- ;
- ; We show relative population changes from decade to decade
- ; via color indices.
- ;
- RangeMax = [1., 1.01, 1.1, 1.2, 1.5, 2., 3.]
- Colors = [ $
- [255, 0, 0], $
- [115, 40, 100], $
- [105, 95, 105], $
- [15, 150, 0], $
- [0, 255, 0], $
- [105, 105, 200], $
- [145, 195, 125], $
- [195, 215, 255]]
- PopulationScale = {RangeMax : RangeMax, Colors : Colors}
- ;
- ; Set the draw window size.
- ;
- DEVICE, GET_SCREEN_SIZE = screenSize
- XDim= 0.55 * screenSize(0)
- YDim= 0.8 * XDim
-
- ;XDim = 467
- ;YDim = 376
-
- If (N_elements(XSize) eq 1) then Begin
- XDim = XSize[0] > 0
- EndIf
- If (N_elements(YSize) eq 1) then Begin
- YDim = YSize[0] > 0
- EndIf
- ;
- ; Restore the States database. This contains
- ; the State outlines and census data.
- ;
- F = FindFile('states.sav', Count = Count)
- If (Count eq 0) then Begin
- Restore, FilePath('states.sav', SubDir = $
- ['examples', 'demo', 'demodata'])
- EndIf Else Begin
- Restore, 'states.sav'
- EndElse
- NStates = N_elements(States)
- NYears = N_elements(States[0].Population)
- For I = 0, NStates - 1 Do Begin
- If (Ptr_Valid(States[I].pLowIndices)) then Begin
- States[I].pOutline = Ptr_New((*States[I].pHighResOutline) $
- [*, *States[I].pLowIndices])
- EndIf Else Begin
- States[I].pOutline = States[I].pHighResOutline
- EndElse
- EndFor
- ;
- ; Calculate State outlines and extruded skirts in normalized
- ; coordinates based on the current window size.
- ;
- USCensus$New_Coordinates, States, XDim, YDim
- ;
- ; Create widgets.
- ;
- If (Keyword_Set(Group_Leader)) then Begin
- wBase = Widget_Base(/COLUMN, Group=Group_Leader, MBar=MenuBar, $
- XPad = 0, YPad = 0, Title = 'US Census Data', $
- /TLB_Kill_Request_Events, /TLB_Size_Events, Space = 0)
- EndIf Else Begin
- wBase = Widget_Base(/COLUMN, MBar = MenuBar, $
- XPad = 0, YPad = 0, Title = 'US Census Data', $
- /TLB_Kill_Request_Events, /TLB_Size_Events, Space = 0)
- EndElse
-
- wBase1 = WIDGET_BASE(wBase,/Row)
-
- AppTLB = wBase
- FileMenu = Widget_Button(MenuBar, Value = 'File', /Menu)
- QuitButton = Widget_Button(FileMenu, Value = 'Quit', /Separator, $
- UValue = 'Quit')
-
- HelpMenu = Widget_Button(MenuBar, Value = 'About', /Help, /Menu)
- HelpButton = Widget_Button(HelpMenu, Value = 'About the data...', $
- UValue = 'HelpCensusData')
- HelpButton = Widget_Button(HelpMenu, Value = 'About the demo...', $
- UValue = 'HelpCensusDemo')
- DataText = [ $
- '', $
- ' This demonstration illustrates United States Census Bureau ', $
- ' data collected in the decades 1790-1990.', $
- '', $
- ' State heights represent total population, while colors', $
- ' indicate relative population change from the preceding', $
- " decade's census.", $
- '', $
- ' States for which no data were collected in the previous', $
- ' decade are displayed in white.']
- DemoText = [ $
- '', $
- ' The "Animate Census" button will cycle through the U.S.', $
- ' Census data from 1790 to 1990. At each decade, the field', $
- ' of view is rotated slightly about the Y-axis, roughly', $
- ' bisecting the map, in order to provide a changing perspective.', $
- ' ', $
- ' The "Rotation Angle" slider widget can be used to explicitly', $
- ' define an angle about the Y-axis at which to view the data.', $
- '', $
- " Clicking on a State will cause the State's name to be", $
- " displayed, illustrating Object Graphics' capabilites for", $
- ' interactively selecting 3D objects.', $
- '', $
- ' The "Select Census Year" pull-down menu lets you select', $
- ' a specific year of data to be shown.', $
- '', $
- " The individual State outlines were derived from IDL's map", $
- ' database.', $
- '', $
- ' This procedure was authored by the Professional Services', $
- ' Group of Research Systems. For those desiring a larger', $
- ' implementation, the Professional Services Group can be', $
- ' contacted (psg@rsinc.com) for consulting and custom coding.']
- wControls = Widget_Base(wBase1, XPad = 1, YPad = 1, Space = 1, $
- /Column, Frame = 1, UValue = 'DoingAnimation')
- AnimateButton = Widget_Button(wControls, Value = 'Animate Census', $
- UValue = 'Animate')
- MenuItem = {CW_PDMENU_S, Flags : 0, Name : ''}
- CensusMenuItems = Replicate(MenuItem, NYears + 1)
- CensusMenuItems.Flags = [1, IntArr(NYears - 1), 2]
- CensusMenuItems.Name = ['Select Census Year', $
- StrTrim(1790 + Indgen(NYears)*10, 2)]
- CensusMenu = CW_PDMenu(wControls, CensusMenuItems, $
- UValue = 'CensusYear', /Return_Index)
- ThetaYSlider = Widget_Slider(wControls, Maximum = 40, Minimum = -40, $
- Value =0, UValue = 'YRotation', Title = 'Rotation Angle')
- Drawbase = Widget_Base(wBase1, /Column, XPad = 0, YPad = 0, Space = 0, Frame = 0)
- wDraw = Widget_Draw(DrawBase, XSize = XDim, YSize = YDim, $
- /Button_Events, UValue = 'Draw', Retain = 0, /Expose_Events, $
- Graphics_Level = 2)
- wScale = Widget_Draw(DrawBase, XSize = XDim, YSize = 60, $
- UValue = 'Legend', Retain = 0, /Expose_Events, $
- Graphics_Level = 2)
-
- ; Create the status line label.
- ;
- wStatusBase = WIDGET_BASE(wBase, MAP=0, /ROW)
-
- nWidgets = 2
- wText = LONARR(nWidgets)
- widTips, wStatusBase, sText.text, XSIZE=36, $
- YSIZE=3, NWIDGETS=nWidgets, wText
-
- ;
- ; Realize the base widget.
- ;
- Widget_Control, wBase, /Realize
-
- ; Size the tips widgets.
- ;
- sizeTips, wBase, wText, wStatusBase
-
- Widget_Control, /Hourglass
- ;
- ; Get the window objects associated with the two
- ; draw widgets we've created.
- ;
- Widget_Control, wDraw, Get_Value = WindowObject
- Widget_Control, wScale, Get_Value = ScaleObject
- ;
- ; Create the views. One will contain the USA and backdrop and
- ; the other will contain the scale legend.
- ;
- ViewObject1 = Obj_New('IDLgrView', Projection = 1, $
- Viewplane_Rect=[-.2, -.11, .4, .22], Color = [255, 255, 255], $
- ZClip = [2., -1.], Depth_Cue = Depth_Cue)
- ViewObject2 = Obj_New('IDLgrView', Projection = 1, $
- Viewplane_Rect=[-1, -1, 2, 2], Color = [0, 0, 0])
- ;
- ; Build the backdrop
- ;
- BackdropModel = Obj_New('IDLgrModel')
- USCensus$Build_Backdrop, BackdropImage, BackdropObject
- BackdropModel->Add, BackdropObject
- If (not Keyword_Set(Backdrop)) then Begin
- BackdropObject->SetProperty, Hide = 1
- EndIf
- ;
- ; Create fonts for labels.
- ;
- Fonts = ObjArr(2)
- Fonts[0] = Obj_New('IDLgrFont', 'Times*Bold', Size = 14 - $
- 2*(!d.y_ch_size gt 12))
- Fonts[1] = Obj_New('IDLgrFont', 'Times', Size = 12 - $
- 2*(!d.y_ch_size gt 12))
- ;
- ; Create the population scale legend, add it to the
- ; appropriate view, and draw it.
- ;
- USCensus$Build_Scale_Legend, PopulationScale, Fonts[1], ScaleModel
- ViewObject2->Add, ScaleModel
- ScaleObject->Draw, ViewObject2
- ;
- ; Create a model for lights and place an ambient and
- ; directional light into the appropriate view.
- ;
- LightFrame = Obj_New('IDLgrModel')
- Light1 = Obj_New('IDLgrLight', Type = 0, Intensity = 0.85, $
- Color = [255, 255, 255])
- Light2 = Obj_New('IDLgrLight', Location = [0, 2, 2], Type = 1, $
- Color = [255, 255, 255], Intensity = .5)
- LightFrame->Add, Light1
- LightFrame->Add, Light2
- ViewObject1->Add, LightFrame
-
- USCensus$Build_State_Objects, States, StateSurfaceModel, $
- StateObjects, StateSkirts, StateFaces, StateOutlines
- ;
- ; If we're only looking at New England, hide the other States.
- ;
- If (NewEngland) then Begin
- For I = 0, NStates - 1 Do Begin
- IsNewEngland = Where(NewEnglandStates eq States[I].State, $
- NIsNewEngland)
- If (NIsNewEngland eq 0) then Begin
- StateObjects[I]->SetProperty, Hide = 1
- EndIf
- EndFor
- EndIf
- ;
- ; Sort of center the USA (or New England) on the origin in the
- ; X-Y plane.
- ;
- ;StateSurfaceModel->Translate, -.46 - NewEngland*.13, $
- ; -.24 - NewEngland*.041, 0.
- StateSurfaceModel->Translate, -.44 - NewEngland*.13, $
- -.24 - NewEngland*.041, 0.
- ;
- ; Scale up New England if we're not looking at the entire USA.
- ;
- If (NewEngland) then Begin
- StateSurfaceModel->Scale, 4., 4., 1.
- EndIf
- ;
- ; Rotate the States 30 degrees about the Y axis. This lets us
- ; look at the Z values from an oblique angle.
- ;
- ThetaY = -30 ;*(1. - (Keyword_Set(Depth)*.75))
- StateSurfaceModel->Rotate, [0., 1., 0.], ThetaY
- ;
- ; Translate the model up Z toward the viewer so we can
- ; make room for the backdrop.
- ;
- StateSurfaceModel->Translate, 0., 0., .5
- ;
- ; Create crosshairs at the origin, if requested.
- ;
- If (Keyword_Set(Axes)) then Begin
- AxisObject = Obj_New('IDLgrModel')
- Xaxis = Obj_New('IDLgrPolyline', [[-.2, 0., 0.], [.2, 0., 0.]], $
- Color=[0, 0, 0], Thick=1.2)
- Yaxis = Obj_New('IDLgrPolyline', [[0., -.2, 0.], [0., .2, 0.]], $
- Color=[0, 0, 0], Thick=1.2)
- Zaxis = Obj_New('IDLgrPolyline', [[0., 0., -.2], [0., 0., .2]], $
- Color=[0, 0, 0], Thick=1.2)
- AxisObject->Add, XAxis
- AxisObject->Add, YAxis
- AxisObject->Add, ZAxis
- ViewObject1->Add, AxisObject
- EndIf
- ;
- ; Add the State surface to the appropriate view.
- ;
- ViewObject1->Add, StateSurfaceModel
- ;
- ; Save the initial transformation matrix. This allows
- ; us to return to this initial position if we want
- ; to re-animate the data.
- ;
- StateSurfaceModel->GetProperty, Transform = InitialTransform
- ;
- ; If we're employing a backdrop image, we only need to draw it
- ; once as an instance and use that in subsequent draws of the USA.
- ;
- If (Keyword_Set(Backdrop)) then Begin
- ViewObject1->Add, BackdropModel
- StateSurfaceModel->SetProperty, Hide = 1
- BackdropModel->SetProperty, Hide = 0
- WindowObject->Draw, ViewObject1, /Create_Instance
- StateSurfaceModel->SetProperty, Hide = 0
- BackdropModel->SetProperty, Hide = 1
- ViewObject1->SetProperty, Transparent = 1
- EndIf
- ;
- ; Add a text object which will hold the census year. It
- ; also holds the name of the State when the user clicks.
- ;
- TextModel = Obj_New('IDLgrModel')
- If (Keyword_Set(Backdrop)) then Begin
- TextColor = [255, 255, 155]
- Endif Else Begin
- TextColor = [0, 0, 0]
- EndElse
- TextObject = Obj_New('IDLgrText', '', Location = [.13, -.08], $
- Color = TextColor, /OnGlass, Font = Fonts[0], Alignment = .5)
- TextModel->Add, TextObject
- ViewObject1->Add, TextModel
- ;
- ; Save the application state.
- ;
- ExceptSave = !except
- !except = 0
- AppState = { $
- ViewObjects : [ViewObject1, ViewObject2], $
- WindowObject : WindowObject, $
- ScaleObject : ScaleObject, $
- wDraw : wDraw, $
- wScale : wScale, $
- wControls : wControls, $
- TextObject : TextObject, $
- States : States, $
- StateObjects : StateObjects, $
- StateOutlines : StateOutlines, $
- StateSkirts : StateSkirts, $
- StateFaces : StateFaces, $
- StateSurfaceModel : StateSurfaceModel, $
- ThetaY : ThetaY, $
- ThetaYSlider : ThetaYSlider, $
- CurrentYearIndex: NYears - 1, $
- Fonts : Fonts, $
- BackdropModel : BackdropModel, $
- BackdropImage : BackdropImage, $
- DepthCue : Depth_Cue, $
- AnimateStates : Keyword_Set(Animate_States), $
- Backdrop : Keyword_Set(Backdrop), $
- PreviousScales : FltArr(N_elements(States)) + 1., $
- MaxZValue : Max(States.Population) * 1.2, $
- PopulationScale : PopulationScale, $
- InitialTransform: InitialTransform, $
- DemoText : DemoText, $
- DataText : DataText, $
- AnimateButton : AnimateButton, $
- ExceptSave : ExceptSave, $
- ColorTable: colorTable, $ ; Color table to restore at exit
- groupBase: groupBase $ ; Base of Group Leader
- }
- Widget_Control, ThetaYSlider, Set_Value = ThetaY
-
- Widget_Control, wBase, Set_UValue = AppState
-
- ;Widget_Control, wBase, /Clear_Events
-
- ; ; Destroy the starting up window.
- ;; ;
- ; WIDGET_CONTROL, drawbase, /DESTROY
- ;
- ; ; Map the top level base.
- ; ;
- ; WIDGET_CONTROL, wBase, MAP=1
- ;
- ;Widget_Control, wBase, /HOURGLASS
-
- USCensus$Display_Census_Year, AppState
- ;
- ; If we're only showing New England, we want to be a little more
- ; fancy; make New England act like a pendulum.
- ;
- ;If (NewEngland and not (Keyword_set(Depth))) then Begin
- ; AppState.WindowObject->SetProperty, QUALITY = (NewEngland eq 1)
- ; For I = 30, 394, 4 Do Begin
- ; Direction = (I mod 180 lt 90) - Long((I mod 180 ge 90))
- ;
- ; Translate the State back to the XY plane, rotate it about Y and Z
- ; then translate it back above the XY plane.
- ;
- ; StateSurfaceModel->Translate, 0., 0., -.5
- ; StateSurfaceModel->Rotate, [0., 1., 0.], 4.*Direction
- ; StateSurfaceModel->Rotate, [0., 0., 1.], 4.*Direction
- ; StateSurfaceModel->Translate, 0., 0., .5
- ; AppState.WindowObject->Draw, AppState.ViewObjects[0], $
- ; Draw_Instance = Keyword_Set(Backdrop)
- ; EndFor
- ;EndIf
- ;Widget_Control, wBase, /Clear_Events
-
-
- XManager, 'D_Uscensus', wBase, $
- /No_Block, $
- CLEANUP='USCensus_Cleanup'
-
- Return
- End
-